package com.demo.thread.future;

import java.util.concurrent.CompletableFuture;

/**
 * @author : YU.TAN
 * @date : 2021/11/2 15:00
 * thenApply与thenApplyAsync
 * <p>
 * thenApply()用于接收supply()返回的执行结果，并执行相关逻辑返回最终执行结果
 * thenApply同步
 * thenApplyAsync异步
 *
 *
 * <p>
 * <p>
 * thenAccept与thenAcceptAsync
 * thenAccep用于接收supply()返回的执行结果，并执行相关逻辑但是不返回最终执行结果，它的返回值是void
 * thenAccept同步
 * thenAcceptAsync异步
 * <p>
 * <p>
 * thenRun
 * 不接收任务的结果，只运行特定的任务，并且也不返回结果。
 * 如果你在回调中不想返回任何的结果，只运行特定的逻辑，那么你可以考虑使用thenAccept和thenRun.
 * 一般来说，这两个方法会在调用链的最后面使用。
 * <p>
 * thenCompose与 thenCombine
 * 它们可以实现对依赖和非依赖两种类型的任务的编排。
 * thenCompose()和thenApply()的核心不同之处在于它们的返回值类型：
 * <p>
 * thenApply()：返回计算结果的原始类型，比如返回String;
 * thenCompose()：返回CompletableFuture类型，比如返回CompletableFuture.
 * <p>
 * thenCombine()将另外两个任务的结果同时作为参数，参与到自己的计算逻辑中。在另外两个参数未就绪时，它将会处于等待状态。
 * <p>
 * 7. allOf与anyOf
 * 用于对多个Future进行组织 相当于CountDownLatch
 * allOf()：给定一组任务，等待所有任务执行结束；
 * anyOf()：给定一组任务，等待其中任一任务执行结束。
 * anyOf()将返回完任务的执行结果，但是allOf()不会返回任何结果，它的返回值是Void.
 * <p>
 * 四、CompletableFuture中的异常处理
 * 在CompletableFuture链式调用中，如果某个任务发生了异常，那么后续的任务将都不会再执行。对于异常，我们有两种处理方式：exceptionally()和handle().
 * 1. 使用exceptionally()回调处理异常
 * 2. 使用handle()处理异常
 * <p>
 * <p>
 * 自定义线程池：当你决定在生产环境使用CompletableFuture的时候，你应该同时准备好对应的线程池策略，而不是偷懒地使用默认的线程池；
 */
public class CompletableFutureC {
    public static void main(String[] args) throws Exception {

        /**
         * 合并写法
         */
        String s = CompletableFuture.supplyAsync(() -> {
            /**
             * 业务逻辑。。。
             */
            return "supplyAsync 测试";
        }).thenApply(resultA -> {
            /**
             * 业务逻辑。。。
             */
            return "thenApply+" + resultA;
        }).get();

        System.out.println(s);


        CompletableFuture.supplyAsync(() -> {
            /**
             * 业务逻辑。。。
             */
            return "supplyAsync 测试 2";
        }).thenAccept(a -> {
            System.out.println(a + "000000");
        });


        String s1 = CompletableFuture.supplyAsync(() -> {
            /**
             * 业务逻辑。。。
             */
            return "thenCompose 测试 1";
        }).thenCompose(a -> {
            return CompletableFuture.supplyAsync(() -> "thenCompose 执行" + a);
        }).get();
        System.out.println(s1);


        /**
         * thenCombine
         */
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "第一个任务！");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "第二个任务！");

        CompletableFuture<String> future = future1.thenCombine(future2, (result1, result2) -> {
            /**
             * 逻辑处理。。。。
             */
            return result1 + result2 + "end";
        });
        String s2 = future.get();
        System.out.println(s2);

        /**
         * allOf()与anyOf()
         */

        CompletableFuture<String> any1 = CompletableFuture.supplyAsync(() -> "第1个任务！");
        CompletableFuture<String> any2 = CompletableFuture.supplyAsync(() -> "第2个任务！");
        CompletableFuture<String> any3 = CompletableFuture.supplyAsync(() -> "第3个d任务！");
        CompletableFuture<String> any4 = CompletableFuture.supplyAsync(() -> "第4个任务！");
        CompletableFuture<String> any5 = CompletableFuture.supplyAsync(() -> "第5个任务！");

        CompletableFuture<Void> future3 = CompletableFuture.allOf(any1, any2, any3, any4, any5);
        System.out.println(future3.get());

        CompletableFuture<Object> future4 = CompletableFuture.anyOf(any1, any2, any3, any4, any5);
        System.out.println(future4.get());


        CompletableFuture<String> future5 = CompletableFuture.supplyAsync(() -> {
//            int a=1/0;
            return "第一个任务！！！！！";
        });
        CompletableFuture<String> future6 = CompletableFuture.supplyAsync(() -> {
            int a = 1 / 0;
            return "第二个任务！！！！！！";
        });

        CompletableFuture<String> future7 = future5.thenCombine(future6, (result1, result2) -> {
            /**
             * 逻辑处理。。。。
             */
            return result1 + result2 + "end";
        }).exceptionally(e -> {
            System.out.println("发生异常+" + e.toString());
            return "";
        });
        String s3 = future7.get();
        System.out.println(s3);


        /**
         * 异常处理
         */
        CompletableFuture<String> future8 = CompletableFuture.supplyAsync(() -> {
//            int a=1/0;
            return "第一个任务！！！！！++++";
        });
        CompletableFuture<String> future9 = CompletableFuture.supplyAsync(() -> {
            int a = 1 / 0;
            return "第二个任务！！！！！！+++++";
        });

        CompletableFuture<String> future10 = future8.thenCombine(future9, (result1, result2) -> {
            /**
             * 逻辑处理。。。。
             */
            return result1 + result2 + "end+++";
        }).handle((res, e) -> {
            if (e != null) {
                System.out.println("发生异常+" + e.toString());
                return "";
            }
            return res;
        });
        String s4 = future10.get();
        System.out.println(s4);
    }
}
